"""
支付管理器 - 统一管理多支付渠道
"""

import frappe
from frappe.utils import now_datetime
from typing import Dict, Any, Optional, List
from upsystem.upsystem.payment_channels.base import PaymentChannelBase
from upsystem.upsystem.payment_channels.fortyseas import FortySeasChannel


class PaymentManager:
    """支付管理器"""
    
    def __init__(self):
        self.channels = {}
        self._load_payment_channels()
    
    def _load_payment_channels(self):
        """加载支付渠道"""
        # 从数据库或配置文件加载支付渠道配置
        channel_configs = self._get_channel_configs()
        
        for channel_name, config in channel_configs.items():
            if channel_name == '40ss':
                self.channels[channel_name] = FortySeasChannel(config)
            # 后续可以添加其他支付渠道
            # elif channel_name == 'stripe':
            #     self.channels[channel_name] = StripeChannel(config)
    
    def _get_channel_configs(self) -> Dict[str, Dict[str, Any]]:
        """获取支付渠道配置"""
        # 这里可以从数据库或配置文件读取
        # 暂时返回硬编码配置，实际应该从数据库读取
        return {
            '40ss': {
                # 沙盒环境（保留以便后续切换使用，仅注释不生效）
                # 'client_id': 'pCTXZxhK19airysAI5wMureHJlhnv1o5',
                # 'client_secret': '_hxYFrKtZIlapO-Ys3UrtHh8rhZ7VMgJ3_hvN0NOBqh2TAolxnE8oy3wA-Mhl-XV',
                # 生产环境参数（当前生效）
                'client_id': '62128a994814c34b11c9474b651a73f2',
                'client_secret': '771f65c32f7cabc4042c063bf384ebb6370445b2a3f10dd328b5cbe032ee97ae',
                'seller_id': 'your_seller_id',
                'is_active': True
            }
        }
    
    def create_payment(self, 
                      payment_channel: str,
                      amount: float,
                      currency: str,
                      company: str = None,
                      paytype: str = 'recharge',
                      recv_user_id: str = None,
                      metadata: Dict[str, Any] = None) -> Dict[str, Any]:
        """
        创建支付
        
        Args:
            payment_channel: 支付渠道 (40ss, stripe, etc.)
            amount: 支付金额
            currency: 货币类型
            company: 公司名称（可选，不传则使用当前用户默认公司）
            paytype: 支付类型 (recharge, order_payment, etc.)
            recv_user_id: 收款用户ID
            metadata: 元数据
            
        Returns:
            Dict: 支付信息
        """
        try:
            # 验证支付渠道
            if payment_channel not in self.channels:
                return {
                    "success": False,
                    "error": f"不支持的支付渠道: {payment_channel}"
                }
            
            channel = self.channels[payment_channel]
            
            # 确定公司
            if not company:
                company = frappe.defaults.get_user_default("Company")
                if not company:
                    return {
                        "success": False,
                        "error": "无法确定公司，请指定company参数或设置用户默认公司"
                    }
            
            # 先创建支付记录
            payment_doc = frappe.get_doc({
                "doctype": "oms_payment",
                "company": company,
                "payment_channel": payment_channel,
                "currency": currency,
                "paytype": paytype,
                "amount": float(amount),
                "status": "pending",
                "notification_status": "pending",
                "notification_times": 0,
                "recv_user_id": recv_user_id,
                "payment_data": frappe.as_json(metadata or {})  # 将 metadata 存储到 payment_data
            })
            payment_doc.insert(ignore_permissions=True)
            
            # 创建结账
            checkout_result = channel.create_checkout(
                amount=amount,
                currency=currency,
                metadata=metadata or {}
            )
            
            if not checkout_result.get('success'):
                # 如果创建结账失败，删除已创建的支付记录
                frappe.delete_doc("oms_payment", payment_doc.name, ignore_permissions=True)
                return {
                    "success": False,
                    "error": f"创建结账失败: {checkout_result.get('error')}"
                }

            checkout_id = checkout_result.get("checkout_id")
            if not checkout_id:
                # 结账成功但未返回 checkout_id，视为异常
                frappe.delete_doc("oms_payment", payment_doc.name, ignore_permissions=True)
                return {
                    "success": False,
                    "error": "创建结账成功但未返回 checkout_id"
                }
            
            # 使用 40Seas 返回的 checkout_id 创建支付意图
            intent_result = channel.create_payment_intent(checkout_id)
            
            if not intent_result.get('success'):
                # 如果创建支付意图失败，删除已创建的支付记录
                frappe.delete_doc("oms_payment", payment_doc.name, ignore_permissions=True)
                return {
                    "success": False,
                    "error": f"创建支付意图失败: {intent_result.get('error')}"
                }
            
            # 更新支付记录
            payment_doc.checkout_id = checkout_id
            payment_doc.payment_url = intent_result.get('payment_url')
            payment_doc.payment_token = intent_result.get('payment_token')
            payment_doc.save(ignore_permissions=True)
            
            return {
                "success": True,
                "data": {
                    "payment_id": payment_doc.name,
                    "checkout_id": checkout_id,
                    "payment_url": intent_result.get('payment_url'),
                    "payment_token": intent_result.get('payment_token'),
                    "amount": amount,
                    "currency": currency,
                    "payment_channel": payment_channel
                }
            }
            
        except Exception as e:
            frappe.logger().error(f"[支付管理器] 创建支付失败: {str(e)}")
            return {
                "success": False,
                "error": str(e)
            }
    
    def get_payment_status(self, payment_id: str) -> Dict[str, Any]:
        """获取支付状态"""
        try:
            payment_doc = frappe.get_doc("oms_payment", payment_id)
            channel = self.channels.get(payment_doc.payment_channel)
            
            if not channel:
                return {
                    "success": False,
                    "error": f"支付渠道 {payment_doc.payment_channel} 不存在"
                }
            
            status_result = channel.get_payment_status(payment_doc.checkout_id)
            
            if status_result.get('success'):
                # 更新本地状态
                payment_doc.status = status_result.get('status', payment_doc.status)
                payment_doc.save(ignore_permissions=True)
            
            return {
                "success": True,
                "data": {
                    "payment_id": payment_id,
                    "status": payment_doc.status,
                    "notification_status": payment_doc.notification_status,
                    "amount": payment_doc.amount,
                    "currency": payment_doc.currency,
                    "payment_channel": payment_doc.payment_channel
                }
            }
            
        except Exception as e:
            frappe.logger().error(f"[支付管理器] 获取支付状态失败: {str(e)}")
            return {
                "success": False,
                "error": str(e)
            }
    
    def handle_webhook(self, payment_channel: str, payload: Dict[str, Any]) -> Dict[str, Any]:
        """处理 Webhook"""
        try:
            if payment_channel not in self.channels:
                return {
                    "success": False,
                    "error": f"不支持的支付渠道: {payment_channel}"
                }
            
            channel = self.channels[payment_channel]
            result = channel.handle_webhook(payload)
            
            # 更新支付记录状态
            checkout_id = payload.get('data', {}).get('id')
            if checkout_id:
                self._update_payment_from_webhook(checkout_id, payload)
            
            return result
            
        except Exception as e:
            frappe.logger().error(f"[支付管理器] 处理 Webhook 失败: {str(e)}")
            return {
                "success": False,
                "error": str(e)
            }
    
    def _update_payment_from_webhook(self, checkout_id: str, payload: Dict[str, Any]):
        """根据 Webhook 更新支付记录"""
        try:
            # 查找对应的支付记录
            payment_docs = frappe.get_all("oms_payment", 
                                        filters={"checkout_id": checkout_id},
                                        fields=["name"])
            
            if not payment_docs:
                frappe.logger().warning(f"[支付管理器] 未找到对应的支付记录: {checkout_id}")
                return
            
            payment_doc = frappe.get_doc("oms_payment", payment_docs[0].name)
            
            # 根据事件类型更新状态
            event_type = payload.get('type')
            if event_type in ['checkout.confirmed', 'checkout.marked_as_paid']:
                payment_doc.status = 'paid'
                payment_doc.notification_status = 'sent'
            elif event_type == 'checkout.failed':
                payment_doc.status = 'failed'
                payment_doc.notification_status = 'failed'
            elif event_type == 'checkout.canceled':
                payment_doc.status = 'canceled'
                payment_doc.notification_status = 'sent'
            
            payment_doc.save(ignore_permissions=True)
            frappe.logger().info(f"[支付管理器] 更新支付记录状态: {payment_doc.name} -> {payment_doc.status}")
            
        except Exception as e:
            frappe.logger().error(f"[支付管理器] 更新支付记录失败: {str(e)}")
            
        # 若状态为已支付，记入余额
        try:
            if payment_doc.status == 'paid':
                _apply_balance_delta(
                    company=payment_doc.company,
                    currency=payment_doc.currency,
                    delta=float(payment_doc.amount or 0),
                    reason='payment_paid',
                    ref_doctype='oms_payment',
                    ref_docname=payment_doc.name,
                )
        except Exception as e:
            frappe.logger().error(f"[支付管理器] 写入余额失败: {str(e)}")
    
    def get_available_channels(self) -> List[Dict[str, Any]]:
        """获取可用的支付渠道"""
        channels = []
        for channel_name, channel in self.channels.items():
            if channel.config.get('is_active', True):
                channels.append(channel.get_channel_info())
        return channels


def _apply_balance_delta(*, company: str, currency: str, delta: float, reason: str, ref_doctype: str = None, ref_docname: str = None) -> None:
    if not company or not currency or not delta:
        return
    # upsert Acct Balance
    bal_name = frappe.db.get_value("Acct Balance", {"company": company, "currency": currency}, "name")
    if not bal_name:
        bal_doc = frappe.get_doc({
            "doctype": "Acct Balance",
            "company": company,
            "currency": currency,
            "balance": 0,
            "last_recalc": now_datetime(),
        })
        bal_doc.insert(ignore_permissions=True)
        bal_name = bal_doc.name
    current = frappe.db.get_value("Acct Balance", bal_name, "balance") or 0
    new_val = float(current) + float(delta)
    update_map = {
        "balance": new_val,
        "last_recalc": now_datetime(),
    }
    # 充值入账时记录最后充值时间
    try:
        if reason == 'payment_paid' and delta > 0:
            update_map["last_recharge_at"] = now_datetime()
    except Exception:
        pass
    frappe.db.set_value("Acct Balance", bal_name, update_map, update_modified=False)
    # 不记录财务流水，仅更新余额
